package br.unifor.ads.desphouse.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import br.unifor.ads.desphouse.jdbc.ConnectionFactory;

/**
 * 
 * @author Alex Girao
 */
public abstract class EntityManager {

	public void executeQuery(String sql, Object... params) throws SQLException {
		PreparedStatement pstm = null;
		Connection conn = null;
		try {
			conn = ConnectionFactory.getConnection();
			pstm = conn.prepareStatement(sql);
			for (int i = 1; i <= params.length; i++) {
				pstm.setObject(i, params[i - 1]);
			}
			pstm.execute();
		} finally {
			this.close(pstm, conn);
		}
	}

	public Object getSingleResult(String sql, Object... params) throws SQLException {
		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet resultSet = null;
		try {
			conn = ConnectionFactory.getConnection();
			pstm = conn.prepareStatement(sql);
			for (int i = 1; i <= params.length; i++) {
				pstm.setObject(i, params[i - 1]);
			}
			resultSet = pstm.executeQuery();
			if (resultSet.next()) {
				return this.trataResultSet(resultSet);
			}
		} finally {
			this.close(conn, pstm, resultSet);
		}
		return null;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List getResultList(String sql, Object... params) throws SQLException {
		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet resultSet = null;
		List results = new ArrayList();
		try {
			conn = ConnectionFactory.getConnection();
			pstm = conn.prepareStatement(sql);
			for (int i = 1; i <= params.length; i++) {
				pstm.setObject(i, params[i - 1]);
			}
			resultSet = pstm.executeQuery();
			while (resultSet.next()) {
				results.add(this.trataResultSet(resultSet));
			}
			return results;
		} finally {
			this.close(conn, pstm, resultSet);
		}
	}

	private void close(PreparedStatement pstm, Connection conn) {
		try {
			if (pstm != null && !pstm.isClosed()) {
				pstm.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if (conn != null && !conn.isClosed()) {
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	private void close(Connection conn, PreparedStatement pstm, ResultSet resultSet) {
		try {
			if (resultSet != null && !resultSet.isClosed()) {
				resultSet.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			close(pstm, conn);
		}
	}

	public abstract Object trataResultSet(ResultSet resultSet) throws SQLException;

}
